JSON output format¶
Example 1 - Serialize the Python output format to JSON¶
import functools
import json
def json_output(decorated):
""" Run the decorated function,
serialize the result of that function to JSON,
and return the JSON string
"""
# Preserving the help of the inner function
@functools.wraps(decorated)
#
def inner(*args, **kwargs):
result = decorated(*args, **kwargs)
return json.dumps(result)
return inner
def func_01(dict):
return dict
@json_output
def func_02(dict):
return dict
d = {'a': 1, 'c': 3, 'b': 2}
res = func_01(d)
print(type(res), res, res['c'])
# <class 'dict'> {'a': 1, 'c': 3, 'b': 2} 3
res = func_02(d)
print(type(res), res, res[2])
# <class 'str'> {"a": 1, "c": 3, "b": 2} a
Example 2¶
class JSONOutputError(Exception):
def __init__(self, message):
self._message = message
def __str__(self):
return self._message
def json_err_output(decorated):
"""Run the decorated function,
serialize the result of that function
to JSON, and return the JSON string.
"""
@functools.wraps(decorated)
def inner(*args, **kwargs):
try:
result = decorated(*args, **kwargs)
except JSONOutputError as ex:
result = {
'status': 'error',
'message': str(ex),
}
return json.dumps(result)
return inner
def func_01():
raise ValueError('Value error message')
# res = func_01()
# print(res)
# Traceback (most recent call last):
# File "<>/deco_output_format.py", line 71, in <module>
# res = error()
# File "<>/deco_output_format.py", line 69, in error
# raise ValueError('Value error message')
# ValueError: Value error message
# Function decorated with @json_err_output raises a JSONOutputError
# and you will get a special error handling
@json_err_output
def func_02():
raise JSONOutputError('This function is erratic.')
res = func_02()
print(res)
# {"status": "error", "message": "This function is erratic."}
Example 3 - decorator with arguments¶
# The difference between an argument passed to the decorator and
# an argument passed to the function at call time is precisely that.
# An argument to the decorator is processed once, when the function is declared and decorated.
# By contrast, arguments to the function are processed when that function is called.
# See: "Professional Python, Luke Sneeringer, Wrox, 2016, p 16.
class JSONOutputError(Exception):
def __init__(self, message):
self._message = message
def __str__(self):
return self._message
def json_err_output(indent=None, sort_keys=False):
""" Run the decorated function,
serialize the result of that function to JSON,
and return the JSON string
"""
def actual_decorator(decorated): # <---
@functools.wraps(decorated)
def inner(*args, **kwargs):
try:
result = decorated(*args, **kwargs)
except JSONOutputError as ex:
result = {
'status': 'error',
'message': str(ex),
}
return json.dumps(result, indent=indent, sort_keys=sort_keys)
return inner
return actual_decorator # <---
@json_err_output(indent=4)
def func_02():
raise JSONOutputError('This function is erratic.')
# return JSON block back with indentation and newlines added
res = func_02()
print(res)
# {
# "status": "error",
# "message": "This function is erratic."
# }